﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Xml.Linq;
using YYTmEditer.MtObject;

namespace yyycommon
{
    class CardSort : IComparer<Card>
    {
        public int Compare(Card x, Card y)
        {
            return string.Compare(x.cardDataID, y.cardDataID);
        }


    }
public class GameObject
    {
        public static GameObject Instance;
        private JObject saveObj;
        private int runtime;

        public List<Blessing> GetBlessing() {
            List<Blessing> bls = saveObj.GetValue("blessings").ToObject<List<Blessing>>();
            return bls;
        }

        public void SetBlessing(List<Blessing> value)
        {
            JArray arr = JArray.FromObject(value);
            //JArray arr = new JArray();
            //foreach(var b in value)
            //{
            //    arr.Add(b);
            //}
            saveObj["blessings"] = arr;
            this.Save();
        }

        public StartCondition GetStartCondition() {
            StartCondition stc = saveObj.GetValue("startingConditions").ToObject<StartCondition>();
            return stc;
        }

        public string GetLevel() {
            int lv = saveObj.GetValue("completedBattles").ToList<JToken>().Count;
            return lv + "/8";
        }

        public List<Card> GetCards() {
            var cards = saveObj.GetValue("deckState").ToObject<List<Card>>();
            List<Card> list = new List<Card>();
            foreach(var it in cards) {
                list.Add(it);
            }
            list.Sort(new CardSort());
            return list;
        }

        public void SetCards(List<Card> cards)
        {
            JArray arr = JArray.FromObject(cards);
            saveObj["deckState"] = arr;
            this.Save();
        }

        public double Gold { get {
                return readValue("gold");

            }
            set{
                setValue("gold", value);

            } 
        }

        public double Hp
        {
            get
            {
                return readValue("towerHP");

            }
            set
            {
                setValue("towerHP", value);

            }
        }

        public double HpMax
        {
            get
            {
                return readValue("maxTowerHP");

            }
            set
            {
                setValue("maxTowerHP", value);

            }
        }

        public bool Save()
        {
            string txt = this.saveObj.ToString(Formatting.None);
            txt = txt.Replace("\"claimed\":true", "\"claimed\":false").Replace("\"seen\":true", "\"seen\":false");
            File.WriteAllText(SavePath(), txt);
            return true;
        }

        public bool load()
        {
            return this.load(false);
        }
        public bool load(bool reload) {
            
            string game = File.ReadAllText(SavePath());
            JObject o = (JObject)JsonConvert.DeserializeObject(game);
            int runtime = o.GetValue("runTime").Value<int>();
            if (this.saveObj == null|| reload)
            {
                this.saveObj = o;
                this.runtime = runtime;
                return false;
            }
            else {
                bool rs = runtime > this.runtime;
                this.runtime = runtime;
                return rs;
            }
            
        }



        string SavePath() {
            Guid localLowId = new Guid("A520A1A4-1780-4FF6-BD18-167343C5AF16");
            return  GetKnownFolderPath(localLowId) + "\\Shiny Shoe\\MonsterTrain\\saves\\save-singlePlayer.json";
        }



        string GetKnownFolderPath(Guid knownFolderId)
        {
            IntPtr pszPath = IntPtr.Zero;
            try
            {
                int hr = SHGetKnownFolderPath(knownFolderId, 0, IntPtr.Zero, out pszPath);
                if (hr >= 0)
                    return Marshal.PtrToStringAuto(pszPath);
                throw Marshal.GetExceptionForHR(hr);
            }
            finally
            {
                if (pszPath != IntPtr.Zero)
                    Marshal.FreeCoTaskMem(pszPath);
            }
        }

        [DllImport("shell32.dll")]
        static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath);

        private double readValue(string name) {
            JObject g = (JObject)this.saveObj.GetValue(name);
            JArray gold = (JArray)g.GetValue("_values");
            byte[] btypes = new byte[16];
            for (int i = 0; i < 16; i++)
            {
                btypes[i] = (byte)gold[i];
            }

            return ObfuscatedNumber.decodeNum(btypes);
        }

        private void setValue(string name, double value) {
            byte[] btypes = new byte[16];
            ObfuscatedNumber.encodeNum(value, btypes);
            JArray jlist = new JArray();
            for(int i = 0; i < 16; i++)
            {
                jlist.Add(btypes[i]);
                Console.Write(btypes[i]);
                Console.Write(",");
            }
            Console.WriteLine(name+"=>" +value);
            this.saveObj[name]["_values"] = jlist;

            //g.Add({ "":""});
        }

        
    }
}
